#include "BoneReader.h"
#include "io.h"

BoneReader::BoneReader(tstring filename)
	:TextReader(filename),
	m_pCurrentBone(NULL),
	m_pCurrentNode(NULL)
{

}

BoneReader::~BoneReader(void)
{
}

void BoneReader::startElement(const XML_Char *name, const XML_Char **atts)
{
	if (wcscmp(name,L"bone") == 0){
		tstring boneName,length,id;
		int i =0;
		while ( atts[i] != NULL )
		{
			tstring attribute = atts[i];
			if ( wcscmp(atts[i],L"name")==0)
				boneName.assign(atts[i+1]);
			else if (wcscmp(atts[i],L"length")==0)
				length.assign(atts[i+1]);
			else if (wcscmp(atts[i],L"id")==0)
				id.assign(atts[i+1]);
			i+=2;
		}
		m_pCurrentBone = new SkeletonNode(boneName,this->ParseInt(id));
		if ( m_pCurrentNode != NULL )
			m_pCurrentNode->AddNode(m_pCurrentBone);
		m_pCurrentNode = m_pCurrentBone;
		m_NodeStack.push(m_pCurrentBone);
	}else if (wcscmp(name,L"node") == 0){
		tstring name;
		int i =0;
		while ( atts[i] != NULL )
		{
			tstring attribute = atts[i];
			if ( wcscmp(atts[i],L"name")==0)
				name.assign(atts[i+1]);
			i+=2;
		}
		m_pCurrentBone =NULL;
		SkeletonNode* sn = new SkeletonNode(name,-1);
		if ( m_pCurrentNode != NULL )
			m_pCurrentNode->AddNode(sn);
		m_pCurrentNode = sn;
		m_NodeStack.push(m_pCurrentNode);
	}else if (wcscmp(name,L"transform") == 0){
		tstring tx,ty,tz,rx,ry,rz,sx,sy,sz;
		int i  =0;
		while( atts[i] != NULL )
		{
			if ( wcscmp(atts[i],L"tx") == 0)
				tx.assign(atts[i+1]);
			else if ( wcscmp(atts[i],L"ty") == 0)
				ty.assign(atts[i+1]);
			else if ( wcscmp(atts[i],L"tz") == 0)
				tz.assign(atts[i+1]);
			else if ( wcscmp(atts[i],L"rx") == 0)
				rx.assign(atts[i+1]);
			else if ( wcscmp(atts[i],L"ry") == 0)
				ry.assign(atts[i+1]);
			else if ( wcscmp(atts[i],L"rz") == 0)
				rz.assign(atts[i+1]);
			else if ( wcscmp(atts[i],L"sx") == 0)
				sx.assign(atts[i+1]);
			else if ( wcscmp(atts[i],L"sy") == 0)
				sy.assign(atts[i+1]);
			else if ( wcscmp(atts[i],L"sz") == 0)
				sz.assign(atts[i+1]);
			i+=2;
		}
		// only valid for a Bone

		m_pCurrentBone->SetTransform(ParseFloat(tx),ParseFloat(ty),ParseFloat(tz),
				ParseFloat(rx),ParseFloat(ry),ParseFloat(rz),
				ParseFloat(sx),ParseFloat(sy),ParseFloat(sz));
	}
}

void BoneReader::endElement(const XML_Char* name)
{
	if (wcscmp(name,L"bone")==0 || wcscmp(name,L"node")==0)
	{
		m_NodeStack.pop();
		if ( m_NodeStack.empty() ){
			m_pSkeleton->AddRoot(m_pCurrentNode);
			m_pCurrentNode = NULL;
		}else{
			m_pCurrentBone = NULL;
			m_pCurrentNode = m_NodeStack.top();
		}
	}else if (wcscmp(name,L"skeleton")==0){
		int size = m_NodeStack.size();
	}
}

void BoneReader::charData(const XML_Char *s, int len)
{

}

bool BoneReader::Read()
{
	m_pSkeleton = new Skeleton();
	bool done = false;
	FILE* file;
	_wfopen_s(&file,GetFileName().c_str(),_T("r"));
	if ( file != NULL ){
		unsigned int length = _filelength(_fileno(file));
		char* buf= new char[length];
		do {

			size_t len = fread(buf, 1, length, file);
			done = len < length;
			if (XML_Parse(buf, len, done)) {
				fprintf(stderr,
					"%s at line %d\n",
					XML_ErrorString(XML_GetErrorCode()),
					XML_GetCurrentLineNumber());
				delete[] buf;
				fclose(file);
				return false;
			}
		} while (!done);
		fclose(file);
		delete []buf;
		return true;
	}else{
		return false;
	}
}